#include "simple_json.h"
#include <string.h>
#include <ctype.h>

char *remove_invisible_chars_exact(char *str)
{
    if (str == NULL)
        return NULL;

    int j = 0;
    for (int i = 0; str[i]; i++)
    {
        if (!iscntrl((unsigned char)str[i]) && str[i] != ' ')
        {
            str[j++] = str[i];
        }
    }
    str[j] = '\0';
    return str;
}

float parse_float_(const char *str)
{
    float value = 0;
    float fraction = 0.0f;
    float divisor = 10.0f;
    int sign = 1;
    int has_decimal = 0;

    // 跳过前导空格
    while (*str == ' ' || *str == '\t')
    {
        str++;
    }

    // 处理符号
    if (*str == '-')
    {
        sign = -1;
        str++;
    }
    else if (*str == '+')
    {
        str++;
    }

    // 解析数字部分
    while (*str != '\0')
    {
        if (*str >= '0' && *str <= '9')
        {
            if (!has_decimal)
            {
                // 整数部分
                value = value * 10.0f + (*str - '0');
            }
            else
            {
                // 小数部分
                fraction = fraction + (*str - '0') / divisor;
                divisor *= 10.0f;
            }
        }
        else if (*str == '.')
        {
            if (has_decimal)
            {
                // 多个小数点，停止解析
                break;
            }
            has_decimal = 1;
        }
        else
        {
            // 遇到非法字符，停止解析
            break;
        }
        str++;
    }

    // 合并整数和小数部分
    value += fraction;

    // 应用符号
    return sign * value;
}

int mjson_parse(const char *_str, get_param_t *param, int len)
{
    char *str = remove_invisible_chars_exact((char *)_str);

    for (int i = 0; i < len; i++, param++)
    {
        char *target = strstr(str, param->key);
        if (NULL == target)
        {
            return -1;
        }

        target = strstr(target, "\":");
        if (NULL == target)
        {
            return -1;
        }
        target += strlen("\":");

        // handle the bool type
        if (TYPE_BOOL == param->type)
        {
            if (*target == 'F' ||
                *target == 'f' ||
                *target == '0')
                *((bool *)param->data) = false;
            else
                *((bool *)param->data) = true;

            return 0;
        }

        float f = parse_float_(target); /*sscanf(target + 2, formats[(int)param->type], param->data);*/
        if (TYPE_FLOAT == param->type)
        {
            *((float *)param->data) = f;
        }
        else if (TYPE_INT == param->type)
        {
            *((int *)param->data) = (int)f;
        }
    }
    return 0;
}

int mjson_get_int(const char *_str, const char *key, int *value)
{
    get_param_t param = {key, TYPE_INT, value};
    return mjson_parse(_str, &param, 1);
}

int mjson_get_float(const char *_str, const char *key, float *value)
{
    get_param_t param = {key, TYPE_FLOAT, value};
    return mjson_parse(_str, &param, 1);
}
int mjson_get_bool(const char *_str, const char *key, bool *value)
{
    get_param_t param = {key, TYPE_BOOL, value};
    return mjson_parse(_str, &param, 1);
}
